package com.digicom.service.article.impl;

import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.digicom.common.constant.Constants;
import com.digicom.common.entity.Article;
import com.digicom.common.entity.PayOrder;
import com.digicom.common.exception.ServiceException;
import com.digicom.common.mapper.ArticleMapper;
import com.digicom.common.mapper.PayOrderMapper;
import com.digicom.service.article.ArticleService;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.kafka.core.KafkaTemplate;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.util.Arrays;
import java.util.Date;
import java.util.List;
import java.util.concurrent.TimeUnit;

/**
 * 文章服务实现类
 */
@Slf4j
@Service
public class ArticleServiceImpl extends ServiceImpl<ArticleMapper, Article> implements ArticleService {

    @Autowired
    private ArticleMapper articleMapper;

    @Autowired
    private PayOrderMapper payOrderMapper;

    @Autowired
    private KafkaTemplate<String, Object> kafkaTemplate;

    @Autowired
    private RedisTemplate<String, Object> redisTemplate;

    @Override
    public Page<Article> listArticlePage(Article article, Page<Article> page) {
        return articleMapper.selectArticlePage(page, article);
    }

    @Override
    public List<Article> listArticlesByTopicId(Long topicId) {
        if (topicId == null) {
            throw new ServiceException("专题ID不能为空");
        }

        LambdaQueryWrapper<Article> wrapper = new LambdaQueryWrapper<>();
        wrapper.eq(Article::getTopicId, topicId)
               .eq(Article::getStatus, Constants.ARTICLE_STATUS_PUBLISHED)
               .orderByAsc(Article::getArticleId);
        return list(wrapper);
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public Long saveArticle(Article article) {
        if (article == null || StringUtils.isBlank(article.getTitle())) {
            throw new ServiceException("文章信息不完整");
        }

        // 设置默认状态
        if (StringUtils.isBlank(article.getStatus())) {
            article.setStatus(Constants.ARTICLE_STATUS_DRAFT);
        }
        article.setSyncApp("0");

        // 设置文章类型
        if (StringUtils.isBlank(article.getArticleType())) {
            article.setArticleType(Constants.ARTICLE_TYPE_FREE);
        }

        // 初始化计数字段
        if (article.getArticleId() == null) {
            article.setViewCount(0L);
            article.setLikeCount(0L);
            article.setCommentCount(0L);
            article.setCollectCount(0L);
            article.setShareCount(0L);
        }

        boolean result;
        if (article.getArticleId() != null) {
            // 更新文章
            result = updateById(article);
        } else {
            // 新增文章
            result = save(article);
        }

        if (!result) {
            throw new ServiceException("保存文章失败");
        }
        
        return article.getArticleId();
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public boolean publishArticle(Long articleId) {
        if (articleId == null) {
            throw new ServiceException("文章ID不能为空");
        }

        Article article = getById(articleId);
        if (article == null) {
            throw new ServiceException("文章不存在");
        }

        // 设置为已发布状态
        article.setStatus(Constants.ARTICLE_STATUS_PUBLISHED);
        // 设置发布时间
        article.setPublishTime(new Date());
        
        boolean result = updateById(article);
        if (result) {
            // 发布成功后，同步到APP
            syncArticleToApp(articleId);
        }
        
        return result;
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public boolean syncArticleToApp(Long articleId) {
        if (articleId == null) {
            throw new ServiceException("文章ID不能为空");
        }

        Article article = getById(articleId);
        if (article == null) {
            throw new ServiceException("文章不存在");
        }

        try {
            // 发送消息到Kafka，通知APP同步文章数据
            kafkaTemplate.send(Constants.TOPIC_ARTICLE_SYNC, article);
            
            // 更新同步状态
            article.setSyncApp("1");
            return updateById(article);
        } catch (Exception e) {
            log.error("同步文章到APP失败", e);
            throw new ServiceException("同步文章到APP失败");
        }
    }

    @Override
    public Article getArticleDetail(Long articleId) {
        if (articleId == null) {
            throw new ServiceException("文章ID不能为空");
        }

        return articleMapper.selectArticleDetail(articleId);
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public boolean deleteArticles(Long[] articleIds) {
        if (articleIds == null || articleIds.length == 0) {
            throw new ServiceException("文章ID不能为空");
        }

        // 逻辑删除文章
        LambdaQueryWrapper<Article> wrapper = new LambdaQueryWrapper<>();
        wrapper.in(Article::getArticleId, Arrays.asList(articleIds));
        return remove(wrapper);
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public boolean updateViewCount(Long articleId) {
        if (articleId == null) {
            throw new ServiceException("文章ID不能为空");
        }

        // 避免频繁更新数据库，先递增Redis中的阅读量
        String key = "article:view_count:" + articleId;
        Long increment = redisTemplate.opsForValue().increment(key);
        
        // 当增量达到一定值或过一段时间，再更新到数据库
        if (increment != null && increment % 10 == 0) {
            articleMapper.updateHitCount(articleId, increment.intValue());
            // 重置Redis中的计数
            redisTemplate.delete(key);
        } else {
            // 设置过期时间，确保最终会更新到数据库
            redisTemplate.expire(key, 1, TimeUnit.HOURS);
        }
        
        return true;
    }

    @Override
    public boolean checkUserPurchased(Long userId, Long articleId) {
        if (userId == null || articleId == null) {
            throw new ServiceException("参数不能为空");
        }

        // 查询文章信息
        Article article = getById(articleId);
        if (article == null) {
            throw new ServiceException("文章不存在");
        }

        // 免费文章无需购买
        if (Constants.ARTICLE_TYPE_FREE.equals(article.getArticleType())) {
            return true;
        }

        // 查询用户是否已购买该文章
        LambdaQueryWrapper<PayOrder> wrapper = new LambdaQueryWrapper<>();
        wrapper.eq(PayOrder::getUserId, userId)
               .eq(PayOrder::getArticleId, articleId)
               .eq(PayOrder::getStatus, Constants.PAY_STATUS_SUCCESS);
        return payOrderMapper.selectCount(wrapper) > 0;
    }

    @Override
    public List<Article> getHotArticles(int limit) {
        // 查询热门文章（根据阅读量和点赞数排序）
        LambdaQueryWrapper<Article> wrapper = new LambdaQueryWrapper<>();
        wrapper.eq(Article::getStatus, Constants.ARTICLE_STATUS_PUBLISHED)
               .orderByDesc(Article::getViewCount)
               .orderByDesc(Article::getLikeCount)
               .last("limit " + limit);
        return list(wrapper);
    }

    /**
     * 更新文章点赞数
     */
    @Override
    public boolean updateLikeCount(Long articleId, int delta) {
        if (articleId == null) {
            return false;
        }
        
        try {
            Article article = getById(articleId);
            if (article == null) {
                return false;
            }
            
            // 更新点赞数，防止出现负数
            Long currentLikes = article.getLikeCount() != null ? article.getLikeCount() : 0L;
            Long newLikes = Math.max(0L, currentLikes + delta);
            article.setLikeCount(newLikes);
            
            return updateById(article);
        } catch (Exception e) {
            log.error("更新文章点赞数失败，articleId={}, delta={}", articleId, delta, e);
            return false;
        }
    }

    /**
     * 更新文章收藏数
     */
    @Override
    public boolean updateCollectCount(Long articleId, int delta) {
        if (articleId == null) {
            return false;
        }
        
        try {
            Article article = getById(articleId);
            if (article == null) {
                return false;
            }
            
            // 更新收藏数，防止出现负数
            Long currentCollects = article.getCollectCount() != null ? article.getCollectCount() : 0L;
            Long newCollects = Math.max(0L, currentCollects + delta);
            article.setCollectCount(newCollects);
            
            return updateById(article);
        } catch (Exception e) {
            log.error("更新文章收藏数失败，articleId={}, delta={}", articleId, delta, e);
            return false;
        }
    }

    /**
     * 更新文章分享数
     */
    @Override
    public boolean updateShareCount(Long articleId, int delta) {
        if (articleId == null) {
            return false;
        }
        
        try {
            Article article = getById(articleId);
            if (article == null) {
                return false;
            }
            
            // 更新分享数，防止出现负数
            Long currentShares = article.getShareCount() != null ? article.getShareCount() : 0L;
            Long newShares = Math.max(0L, currentShares + delta);
            article.setShareCount(newShares);
            
            return updateById(article);
        } catch (Exception e) {
            log.error("更新文章分享数失败，articleId={}, delta={}", articleId, delta, e);
            return false;
        }
    }
} 